package com.hw.one.dam2.dao;

import com.hw.one.dam2.param.MovingDeviceParam;
import com.hw.one.dam2.po.PatrolDataPo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Copyright 2017 汉威.智慧环保事业部.
 * Created by 李亚坤 on 2017/07/18 15:31.
 */
@Repository(value = "patrolTrackDao")
public class PatrolTrackDao implements IPatrolTrackDao{

    @Autowired
    private MongoTemplate mongoTemplateStandardSiteData;

    private static String tableName = "T_DATA_DEVICE_PATROL_TRACK";

    @Override
    public void savePatrolDeviceTrackData(Map<String, Object> paramMap) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        mongoTemplateStandardSiteData.insert(paramMap, tableName + "-" + year);
    }

    @Override
    public List<Map> findPatrolTrackNew50ByDeviceCode(String deviceCode) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        String tableStr = "";
        if (month < 10) {
            tableStr = year + "0" + month;
        }else {
            tableStr = year + "" + month;
        }

        Criteria criteria = Criteria.where("DEVICECODE").is(deviceCode);

        Query query = new Query(criteria);
        // 限制返回字段
        query.fields().include("DEVICECODE").include("LONGITUDE").include("LATITUDE").include("MONITORTIME").exclude("_id");
        // 增加排序功能
        query.with(new Sort(Sort.Direction.DESC, "MONITORTIME")).limit(50);
        return mongoTemplateStandardSiteData.find(query, Map.class, tableName + "-" + tableStr);
    }

    @Override
    public List<Map> findPatrolTrackRealDataByDeviceCodes(List<String> deviceCodeList) {
        Criteria criteria = Criteria.where("DEVICECODE").in(deviceCodeList);

        Query query = new Query(criteria);
        // 查询轨迹信息实时表
        return mongoTemplateStandardSiteData.find(query, Map.class, tableName);
    }

    @Override
    public List<PatrolDataPo> findPatrolTrackRealDataByDeviceCodesAndStatus(MovingDeviceParam movingDeviceParam) {
        Criteria criteria = Criteria.where("DEVICECODE").in(movingDeviceParam.getDeviceCodeList());
        if (!StringUtils.isEmpty(movingDeviceParam.getDeviceStatus())) {
            criteria.and("DEVICESTATUS").is(movingDeviceParam.getDeviceStatus());
        }
        if (!StringUtils.isEmpty(movingDeviceParam.getStartTime()) && !StringUtils.isEmpty(movingDeviceParam.getEndTime())) {
            criteria.and("MONITORTIME").gte(movingDeviceParam.getStartTime()).lte(movingDeviceParam.getEndTime());
        }

        Query query = new Query(criteria);
        return mongoTemplateStandardSiteData.find(query, PatrolDataPo.class, tableName);
    }

    @Override
    public List<PatrolDataPo> findPatrolTrackRealDataByDeviceCodesAndLocScope(MovingDeviceParam movingDeviceParam) {
        // 创建查询条件
        // 设备编码列表
        Criteria criteria = Criteria.where("DEVICECODE").in(movingDeviceParam.getDeviceCodeList());
        // 创建圆形形，传入 中心点和半径
        Circle circle = new Circle(movingDeviceParam.getLocation()[0], movingDeviceParam.getLocation()[1], movingDeviceParam.getRadius());
        // 增加查询条件loc，在多边形区域内的坐标
        criteria.and("loc").withinSphere(circle);
        Query query = new Query(criteria);
        /*
         * Criteria 的一些操作参考，官方文档
         * http://docs.spring.io/spring-data/data-mongo/docs/current/api/org/springframework/data/mongodb/core/query/Criteria.html
         */
        return mongoTemplateStandardSiteData.find(query, PatrolDataPo.class, tableName);
    }

    @Override
    public List<PatrolDataPo> findPatrolTrackRealDataByLocation(MovingDeviceParam movingDeviceParam) {
        // 创建查询条件
        // 设备编码列表
        Criteria criteria = Criteria.where("DEVICECODE").in(movingDeviceParam.getDeviceCodeList());
        // 循环点位
        List<Point> pointList = new ArrayList<>();
        for (double[] locationList : movingDeviceParam.getLocationList()) {
            // 创建Point
            Point point = new Point(locationList[0], locationList[1]);
            pointList.add(point);
        }
        // 创建多边形，Polygon是Shape的实现类，代表多边形，传入参数可以是Point的集合
        Shape shape = new Polygon(pointList);
        // 增加查询条件loc，在多边形区域内的坐标
        criteria.and("loc").within(shape);
        Query query = new Query(criteria);
        /*
         * Criteria 的一些操作参考，官方文档
         * http://docs.spring.io/spring-data/data-mongo/docs/current/api/org/springframework/data/mongodb/core/query/Criteria.html
         */
        return mongoTemplateStandardSiteData.find(query, PatrolDataPo.class, tableName);
    }

    @Override
    public List<Map> findPatrolTrackByTimeAndGroupByCodes(MovingDeviceParam movingDeviceParam) {
        String year = movingDeviceParam.getStartTime().substring(0, 7).replace("-", "");
        // 查询条件
        Criteria criteria = Criteria.where("MONITORTIME").gte(movingDeviceParam.getStartTime()).lte(movingDeviceParam.getEndTime());
        criteria.and("DEVICECODE").in(movingDeviceParam.getDeviceCodeList());

        // 创建操作对象
        MatchOperation matchOperation = Aggregation.match(criteria);

        // 分组对象及操作
        GroupOperation groupOperation = Aggregation.group("DEVICECODE").
                max("$MONITORTIME").as("MONITORTIME").
                count().as("count");
        // 组合条件
        Aggregation aggregation = Aggregation.newAggregation(
                matchOperation,
                groupOperation
        );
        // 执行操作
        AggregationResults<Map> aggregate = mongoTemplateStandardSiteData.aggregate(aggregation, tableName + "-" + year, Map.class);
        return aggregate.getMappedResults();
    }

    @Override
    public List<PatrolDataPo> findPatrolTrackByDeviceCodeAndTime(Map<String, Object> paramMap) {
        Criteria criteria = Criteria.where("DEVICECODE").is(paramMap.get("deviceCode"));
        criteria.and("MONITORTIME").gte(paramMap.get("startTime")).lte(paramMap.get("endTime"));

        Query query = new Query(criteria).with(new Sort(Sort.Direction.DESC, "MONITORTIME"));
        String year = paramMap.get("startTime").toString().substring(0, 7).replace("-", "");
        return mongoTemplateStandardSiteData.find(query, PatrolDataPo.class, tableName + "-" + year);
    }
}
